package com.tn.service.usermanagement.impl;

import com.tn.auth.utils.TokenUtil;
import com.tn.controller.alarm.common.enums.CommonCodeEnum;
import com.tn.controller.alarm.common.model.CommonVO;
import com.tn.controller.alarm.common.model.PageInput;
import com.tn.controller.alarm.common.model.PageResult;
import com.tn.controller.alarm.common.model.user.entity.DeptDO;
import com.tn.controller.alarm.common.model.user.entity.Menu;
import com.tn.controller.alarm.common.model.user.vo.MenuUserVo;
import com.tn.controller.alarm.common.model.user.vo.UserVO;
import com.tn.dao.usermanagement.IUserManagementDao;
import com.tn.exception.DatabaseOperationFailedException;
import com.tn.service.usermanagement.IUserManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.ArrayList;
import java.util.List;

/**
 * 人员管理实现类
 *
 * @program: tn_aucy_java
 * @author: yangjiayao
 * @create: 2021/12/24
 */
@Slf4j
@Service
public class UserManagementServiceImpl implements IUserManagementService {
    /**
     * 数据访问层
     */
    private IUserManagementDao userManagementDao;

    /**
     * 注入
     *
     * @param userManagementDao userManagementDao
     */
    @Autowired
    public void setUserManagementDao(IUserManagementDao userManagementDao) {
        this.userManagementDao = userManagementDao;
    }

    @Override
    @Transactional
    public CommonVO<Object> addDept(DeptDO dept) throws DatabaseOperationFailedException {
        if (checkExistsDept(dept.getDeptName())) {
            throw new DatabaseOperationFailedException(CommonCodeEnum.EXISTS.getCode(),
                    CommonCodeEnum.EXISTS.getMessage());
        }
        int num = userManagementDao.addDept(dept);
        if (1 != num || null == dept.getId()) {
            log.error("Unexpect return num or id!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.UNKNOWN.getCode(),
                    CommonCodeEnum.UNKNOWN.getMessage());
        }
        return new CommonVO<>();
    }

    @Override
    @Transactional
    public CommonVO<Object> deleteDept(DeptDO dept) throws DatabaseOperationFailedException {
        int num = userManagementDao.queryUserByDept(dept.getId());
        if (0 < num) {
            log.error("delete dept failed: Users of this dept are exists!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.DATA_BIND.getCode(),
                    CommonCodeEnum.DATA_BIND.getMessage());
        }
        num = userManagementDao.deleteDept(dept.getId());
        if (1 != num) {
            log.error("Unexpect return num!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_EXISTS.getCode(),
                    CommonCodeEnum.NOT_EXISTS.getMessage());
        }
        return new CommonVO<>();
    }

    @Override
    @Transactional
    public CommonVO<Object> modifyDept(DeptDO dept) throws DatabaseOperationFailedException {
        if (checkExistsDept(dept.getDeptName())) {
            throw new DatabaseOperationFailedException(CommonCodeEnum.EXISTS.getCode(),
                    CommonCodeEnum.EXISTS.getMessage());
        }
        int num = userManagementDao.modifyDept(dept);
        if (1 != num) {
            log.error("Unexpect return num!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_EXISTS.getCode(),
                    CommonCodeEnum.NOT_EXISTS.getMessage());
        }
        return new CommonVO<>();
    }

    @Override
    public CommonVO<PageResult<DeptDO>> queryDept(PageInput<DeptDO> pageDept) {
        CommonVO<PageResult<DeptDO>> resultCommonVO = new CommonVO<>();
        int total = userManagementDao.queryDeptCount(pageDept.getData());
        PageResult<DeptDO> result = new PageResult<>(pageDept.getCurPage(), pageDept.getPageSize(), total);
        if (0 < total) {
            result.setData(userManagementDao.queryDeptByPage(result.getStartIndex(), pageDept.getPageSize(),
                    pageDept.getData()));
        }
        resultCommonVO.setData(result);
        return resultCommonVO;
    }

    @Override
    @Transactional
    public CommonVO<Object> addUser(UserVO user) throws DatabaseOperationFailedException {
        if (checkExistsUser(user.getUserName(), null)) {
            throw new DatabaseOperationFailedException(CommonCodeEnum.EXISTS.getCode(),
                    CommonCodeEnum.EXISTS.getMessage());
        }
        int num = userManagementDao.addUser(user);
        if (1 != num || null == user.getUserId()) {
            log.error("Unexpect return num or id!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.UNKNOWN.getCode(),
                    CommonCodeEnum.UNKNOWN.getMessage());
        }
        return new CommonVO<>();
    }

    @Override
    @Transactional
    public CommonVO<Object> deleteUser(UserVO user) throws DatabaseOperationFailedException {
        int num = userManagementDao.deleteUser(user.getUserId());
        if (1 != num) {
            log.error("Unexpect return num!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_EXISTS.getCode(),
                    CommonCodeEnum.NOT_EXISTS.getMessage());
        }
        TokenUtil.tokenList.remove(String.valueOf(user.getUserId()));
        return new CommonVO<>();
    }

    @Override
    @Transactional
    public CommonVO<Object> modifyUser(UserVO user) throws DatabaseOperationFailedException {
        if (null != user.getUserName() && checkExistsUser(user.getUserName(), user.getUserId())) {
            throw new DatabaseOperationFailedException(CommonCodeEnum.EXISTS.getCode(),
                    CommonCodeEnum.EXISTS.getMessage());
        }
        int num = userManagementDao.modifyUser(user);
        if (1 != num) {
            log.error("Unexpect return num!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_EXISTS.getCode(),
                    CommonCodeEnum.NOT_EXISTS.getMessage());
        }
        TokenUtil.tokenList.remove(String.valueOf(user.getUserId()));
        return new CommonVO<>();
    }

    @Override
    public CommonVO<PageResult<UserVO>> queryUser(PageInput<UserVO> pageUser) {
        CommonVO<PageResult<UserVO>> resultCommonVO = new CommonVO<>();
        int total = userManagementDao.queryUserCount(pageUser.getData());
        PageResult<UserVO> result = new PageResult<>(pageUser.getCurPage(), pageUser.getPageSize(), total);
        if (0 < total) {
            result.setData(userManagementDao.queryUserByPage(result.getStartIndex(), pageUser.getPageSize(),
                    pageUser.getData()));
        }
        resultCommonVO.setData(result);
        return resultCommonVO;
    }

    @Override
    @Transactional
    public CommonVO<Object> modifySuperUser(UserVO user) throws DatabaseOperationFailedException {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (null == requestAttributes) {
            CommonVO<Object> result = new CommonVO<>();
            result.setCode(CommonCodeEnum.UNKNOWN.getCode());
            result.setMsg(CommonCodeEnum.UNKNOWN.getMessage());
            return result;
        }
        String operateUser =
                ((ServletRequestAttributes) requestAttributes).getRequest().getHeader(TokenUtil.USER_PARAM_NAME);
        int num = userManagementDao.checkSuperUser(Integer.parseInt(operateUser));
        if (1 != num) {
            log.error("Not authorized to grant super user!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_AUTHORIZED.getCode(),
                    CommonCodeEnum.NOT_AUTHORIZED.getMessage());
        }
        num = userManagementDao.modifySuperUser(user.getUserId(), user.getIsSuperuser());
        if (1 != num) {
            log.error("Unexpect return num!");
            throw new DatabaseOperationFailedException(CommonCodeEnum.NOT_EXISTS.getCode(),
                    CommonCodeEnum.NOT_EXISTS.getMessage());
        }
        TokenUtil.tokenList.remove(String.valueOf(user.getUserId()));
        return new CommonVO<>();
    }


    @Override
    public CommonVO<Object> addMenu(Menu menu) {
        userManagementDao.addMenu(menu);
        return new CommonVO<>();
    }

    @Override
    public CommonVO<Object> editMenu(Menu menu) {
        userManagementDao.editMenu(menu);
        return new CommonVO<>();
    }

    @Override
    public CommonVO<Object> deleteMenu(Long id) {
        CommonVO<Object> objectCommonVO = new CommonVO<>();
        //菜单是否被绑定，绑定需要先删除绑定关系再删菜单
        Integer count=userManagementDao.selectMenuBind(id);
        if(count!=null && count>0){
            objectCommonVO.setCode(CommonCodeEnum.DATA_BIND.getCode());
            objectCommonVO.setData(CommonCodeEnum.DATA_BIND.getMessage());
            return objectCommonVO;
        }
        userManagementDao.deleteMenu(id);
        return objectCommonVO;
    }


    @Override
    public CommonVO<Object> selectAllMenu(Long id) {
        List<Menu> menuList=new ArrayList<>();
        //查询登录用户是否是管理员，是就查所有菜单，不是就查绑定菜单
        Integer superAdmin=userManagementDao.isSuperAdmin(id);
        if(superAdmin==0){
            menuList=userManagementDao.selectMenuByUserId(id);
        }else {
            menuList=userManagementDao.selectAllMenu();
        }
        return new CommonVO<>(menuList);
    }


    /**
     * 校验是否存在同名部门
     *
     * @param deptName 部门名称
     * @return 结果
     */
    private boolean checkExistsDept(String deptName) {
        int exists = userManagementDao.checkExistsDept(deptName);
        return 0 < exists;
    }

    /**
     * 校验是否存在同名用户
     *
     * @param userName 用户名
     * @return 结果
     */
    private boolean checkExistsUser(String userName, Integer exceptId) {
        int exists = userManagementDao.checkExistsUser(userName, exceptId);
        return 0 < exists;
    }


    @Override
    public CommonVO<Object> bindUserMenu(MenuUserVo vo) {
        //删除原来的，绑定最新的
        userManagementDao.deleteUserMenu(vo.getUserId());

        userManagementDao.addMenuUser(vo.getUserId(),vo.getMenuIds());
        return new CommonVO<>();
    }

}
